\documentclass{article}
\usepackage{latexsym}
\usepackage[utf8]{inputenx}
\usepackage[spanish]{babel}
\usepackage{graphicx}
\usepackage{anysize}
\usepackage{amsmath}
\usepackage{float}
\setlength{\skip\footins}{5cm}
\usepackage{lscape}
\usepackage{footnote}
\usepackage{pdfpages}
\usepackage{verbatim}
\usepackage{moreverb}
\usepackage{listings}
\usepackage{hyperref}
\let\verbatiminput=\verbatimtabinput

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%     PORTADA     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%    MARGENES     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\marginsize{2cm}{2cm}{.5cm}{3cm} 


\title{ 66.71:Teoría del Lenguaje - Presentación Eiffel }

\author{ Gonzalo Beviglia \and Federico Quevedo} 

\date{ \today }

\begin{document}

% Title and Table of Contents %
\maketitle
\tableofcontents
\newpage

\section{Introducción}
El lenguaje de programación Eiffel es un lenguaje que fue estandarizado por la organización
ISO. Es un lenguaje orientado a objetos que soporta, y fomenta, el diseño por contratos. La
filosofía de los desarrolladores y diseñadores de este lenguaje de programación llevaron a
que el mismo se base en metodologías ágiles y buenas prácticas de programación.

Algunas de estas buenas prácticas son:
\begin{itemize}
\item Separación comando-consulta
\item Principio de acceso uniforme
\item Principio abierto-cerrado
\item Separación de opciones-operandos
\end{itemize}

\section{Historia}
Eiffel fue desarrollado por Betrand Meyer y Eiffel Software, y su primera versión fue publicada
en 1985. Eiffel Software, a su vez, es una empresa fundada por Meyer. En la década de 1980, cuando
surge Eiffel como lenguaje de programación, la programación orientada a objetos estaba creciendo
de manera muy rápida. Era un concepto nuevo, que no todos terminaban de entender. Esto llevo a que
el término ``orientado a objetos'' se banalizara y cobrara distinto sentido dependiendo de quien
lo utilizara.

Meyer considera que el lenguaje que más aportaba y que mejor representaba a la programación orientada
a objetos era Simula. Para muchos, Simula fue el primer lenguaje orientado a objetos, y se utilizaba,
como su nombre bien lo indica para realizar simulaciones.

Eiffel comienza como una herramienta para desarrollar aplicaciones internas de la empresa Eiffel Software.
Eiffel es pensado como una solución integral, un framework en el cual se desarrollan aplicaciónes siguiendo
buenas prácticas, que utiliza el lenguaje Eiffel Language. Eiffel Studio es un IDE que provee todas las
herramientas que uno puede necesitar para analizar, diseñar y desarrollar una aplicación.

Sucesivas versiones del ambiente fueron apareciendo con una frecuencia de alrededor de una por año. La exposición
del lenguaje aumentó dramáticamente luego de la publicación, en 1988, del libro ``Object-Oriented Software Construction'',
escrito por Bertrand Meyer, que se convirtió rápidamente en un best-seller y fue traducido en ocho lenguajes. El libro
utilizó Eiffel para explicar e ilustrar los conceptos fundamentales de los objetos y del diseño por contrato.

La última iteración de la tecnología original fue la versión 2.3, publicada en el verano de 1990. La siguiente versión,
Eiffel 3, fue escrita íntegramente en Eiffel. Eiffel 3 introduce la tecnología ``Meltin Ice'' para una rápida compilación,
un entorno totalmente gráfico basado en conceptos innovadores de interfaz de usuario, avances considerables en sus
librerias (gráficas, redes, etc) y la optimización de código generado.

Hoy en día, la tecnología Eiffel continúa rompiendo las barreras del desarrollo de software. Con la intrudocción de
EiffelStudio, los programadores pueden aprovecharse de un IDE eficiente para poder obtener la mejor calidad,
robustez, escalabilidad y reusabilidad de aplicaciones.

\subsection{La revolución estructurada}

La programación estructurada surge como un paradigma que apunta a mejorar la calidad y la claridad del
código fuente. Para lograrlo, se hace un uso extensivo de estructuras de bloque, subrutinas, ciclos ``for''
y ``while''. Este paradigma nace como contrapartida de lo que se llama ``código spaghetti'', generado
por el uso de sentencias ``goto'' que eran tan usuales previo a 1960.

Las prácticas que Meyer sugiere que deben cambiar de esta ``revolución estructurada'' son:
\begin{itemize}
\item Diseño top-down
\item Hostilidad ante el testing
\item Diseño estructurado
\end{itemize}

\subsubsection{Diseño top-down}
Los beneficios de este tipo de diseño, que surge de analizar los requerimientos de la aplicación ``desde arriba'',
es que se asocian con una mirada intuitiva del problema. Analizar desde este ángulo es racional, ya que se describen
las partes que componen al producto final desde lo tangible y utilizable. Uno empieza desde lo que uno espera que
el producto sea y luego se va especificando que partes compondrán a este todo. Además es una práctica sistemática,
que no requiere de mucho entrenamiento.

Los puntos en contra con los que cuenta este tipo de diseño son, mayormente, puntos que el diseño orientado a objetos
intenta cambiar desde su gestación. El diseño estructurado, al ser visto desde un producto final, no tiene en cuenta
la necesidad de cambiar y de adaptarse a nuevos requerimientos. Tampoco se tiene en cuenta la necesidad de reutilizar
módulos en otras aplicaciones, ya que los módulos surgen en respuesta a una necesidad específica.

El modelo Eiffel es resolutivamente bottom-up ya que, al ser orientado a objetos, apunta a fomentar la reutilización
y la facilidad de cambio.

\subsubsection{Testing}
``Testing can never be used to show the absence of bugs, only to show their presence.'' Edsger Dijkstra

Los argumentos en contra del testing, por parte de los desarrolladores del paradigma estructurado nacen de la dificultad
de adecuar el modelo del sistema con el que ya cuentan a un paquete de pruebas. Se considera que las pruebas formales no
pueden ser aplicadas a muchos sistemas complejos de la época. Además, generar pruebas formales es un proceso tedioso que
no todos los desarrolladores están en condiciones de realizar. Por otro lado, se consideraba que el testing solo verificaba
desviaciones de la especificación. Se creía que la única razon por la que el testing podía desembocar en la mejor de la
aplicación era porque se estaba utilizando la misma.

Nuevamente, al ser Eiffel un lenguaje orientado a objetos, se cree que el testing está en la naturaleza del paradigma. Un
buen paquete de pruebas funciona como base para determinar si la aplicación está funcionando como debería o si su
comportamiento no es el esperado. De esta manera, luego de tener una aplicación funcionando, se pueden modificar algunos
de sus módulos y, por medio del paquete de pruebas, se puede verificar si su comportamineto dejó de ser el correcto.

\subsubsection{Diseño estructurado}

El diseño que se realizaba bajo el paradigma estructurado puso de acuerdo a la industria informática bajo dos ideas fundamentales:

\begin{itemize}
\item El diseño es un arte noble, en contraposición con la ``programación'', una ocupación que puede ser realizada por cualquiera
\item Este arte se lleva a cabo dibujando círculos y flechas
\end{itemize}

El problema fue que este proceso de diseño se trivializó y no se apreciaban los beneficios que podía traer el diseño al
estado final de un sistema o aplicación.

\section{Buenas prácticas}
\subsection{Separación comando-consulta}
Este concepto fue inventado por Bertrand Meyer. Lo que dice es que todo método debe ser un comando que realiza una
acción o una consulta que devuelve datos a su invocador, pero no ambos. Al cumplir con esto, minimizamos los
``efectos secundarios'' que tiene un método y reducimos la posibilidad de sorprender al usuario de los métodos.

Cumplir con este principio hace que tengamos un código más simple y más entendible ya que se pueden seguir con
facilidad los cambios de estado del sistema y se pueden identificar a los responsables de dicho cambio.

\subsection{Acceso uniforme}
Todos los servicios ofrecidos por un módulo deben poder ser consumidos mediante una notación uniforme, independiente
de la implementación que estos tengan. No debería haber diferencia entre trabajar con un atributo, una propiedad
o un método.

Este principio apunta a facilitar el cambio de implementación de un método consumido por módulos clientes. Al
independizar el nombre del método de su implementación, somos capaces de modificar dicha implementación sin
realizar modificación alguna del lado del cliente.

\subsubsection{Ejemplo en Python}

Si tenemos la clase huevo, con los atributos ``color'', ``peso'' y el método cuack, podriamos
representarlo de dos maneras distintas. Ambas accederían a estos valores de la siguiente manera:

\begin{verbatim}
huevo = Huevo( 4, "Blanco")
huevo.color = "Verde"
print huevo.weight, huevo.color, huevo.romper()
\end{verbatim}

Una manera de modelar esto sería por medio de atributos. Pero, aunque en este caso no se aprecia,
si en algun futuro quisieramos tener algun condicional con respecto al color que se devuelve o se setea,
no podríamos hacerlo directamente con atributos.

\begin{verbatim}
class Huevo(object):
   def __init__(self, peso, color):
      self.peso = peso
      self.color = color
   def romper(self):
      return "Estoy roto"
\end{verbatim}

La manera de implementar el principio de acceso uniforme en Python es mediante el uso de propiedades,
de la siguiente manera:

\begin{verbatim}
class Huevo(object):
    def __init__(self, peso, color):
      self.__peso = aGramos(peso)
      self.__color = aRGB(color)
 	
 	# Vemos que se hace una conversión interna del color que se recibe
    def setColor(self, color):
      self.__color = aRGB(color)
 
    def getColor(self):
      return obtenerNombreDelColor(self.__color)
 	
 	# La propiedad tiene una documentación.
    color = property(getColor, setColor, doc="Color del huevo")
 	
 	# Conversion de onzas a gramos.
    def setPeso(self, pesoOz);
       self.__peso = 29.3*pesoOz
 
 	# Conversion de gramos a onzas.
    def getPeso(self):
       return self.__peso/29.3;
 
    peso = property(setPeso, getPeso, doc="Peso en onzas")
 
    def romper(self):
       return "Estoy roto"
\end{verbatim}

En Eiffel, el manejo de propiedades es intrínseco a la definición de la variable.

\begin{verbatim}
color: TIPO_RGB assign setear_color
   
setear_color (nombre_color: STRING)
    -- Transformo el color recibido a RGB y se lo asigno a la variable color.
    do
        color := aRGB(nombre_color)
    end
\end{verbatim}

\subsection{Abierto-cerrado}
En la programación orientada a objetos, este principio indica que las entidades (clases, módulos, funciones, etc)
deben estar abiertas para la extensión y cerradas para la modificación. Esto quiere decir que debemos ser capaces
de modificar el comportamiento de una entidad sin necesidad de tener que cambiar su código fuente.

Esto es muy importante en ambientes de producción, ya que si modificaramos el código fuente de un módulo, habría
que volver a revisar el mismo. Se apunta a que este proceso no se tenga que volver a realizar una vez aprobado
el módulo. Al extender el funcionamiento del mismo, se deberá probar únicamente el comportamiento que fue modificado
en el módulo que extiende.

\subsection{Separación de opciones-operandos}
Los argumentos de una operación sólo deben ser operandos y no opciones. Las opciones que se pueden utilizar para
modificar el comportamiento de una operación deben ser seteadas por medio de otra operación. De esta manera
logramos un equilibrio entre los expertos, que conocen y requieren de todas las opciones que el módulo provee,
y los principiantes, que utilizan el comportamiento estandar de una función o módulo.

Por otro lado, las opciones son más propensas al cambio que los operandos. Si las opciones implicaran un cambio
en la firma del método, estaríamos en la situación de tener que modificar código fuente del lado del cliente
en caso de cambio.

Un ejemplo de una tabla de hash en el que los features se dividen en categorías. Tenemos separados los features
de acceso de los de cambios de estado:

\begin{verbatim}
class HASH_TABLE [ELEMENT, KEY -> HASHABLE]
    
    inherit TABLE [ELEMENT]
 
    feature -- Inicializacion
        -- Constructores
 
    feature -- Accesso
        -- No se modifica el estado interno del hash.
        obtenerValor(clave: STRING)
            do
                ...
            end
 
    feature -- Cambio de estado
        -- No se devuelve ningun valor o codigo de salida.
        setearValor(clave: STRING, valor: STRING)
            do
                ...
            end
end
\end{verbatim}

\subsection{Limitaciones}
Con la imposicion de buenas practicas impuesta por Eiffel aparecieron ciertas limitaciones como:
\begin{itemize}
\item No hay variables globales, como su uso esta enormemente desestimado y gracias a la estructura de clases de 
Eiffel se evito tenerlas.
\item No existe el tipo union, por ser un tipo de datos poco claro se fuerza a declarar todas las variables.
\item No existe sobrecarga de metodos, debido a las confusiones que esto puede ocasionar.
\item No existe el Goto. La epoca en la que aparecio Eiffel fue proxima al a publicacion hecha por Dijstra 
``Go To Statement Considered Harmful'' que desestimaba el uso de éste.
\item No existen punteros, mas que la clase POINTER usada como interfaz entre Eiffel y C.
\end{itemize}

\section{Features}

Para comenzar a entender la estructura de clases de Eiffel hay que comenzar con el concepto de Feature.
Desde el lado del cliente tenemos que si un llamado no devuelve un resultado, sino que afecta el estado 
interno de la clase estamos tratando con un Comando que hace referencia a un procedimiento, si este llamado 
si devuelve un resultado es una Consulta, que puede ser una funcion si obtuvo dicho resultado a traves de 
una computación o un atributo si lo hizo solo accediendo a memoria.

Desde el lado interno de la clase tenemos que si el llamado solo accede a memoria se trata de un atributo, 
luego un llamado que realize algun computacion es una rutina que, si devuelve algun resultado hace referencia
a una funcion, y si no lo devuelve es un procedimiento.

Los features vendrían a representar tanto atributos como métodos, y cuentan con un manejo de visibilidad
que se tocará más adelante en el informe. Un ejemplo de feature de inicialización es el que se ve
a continuación:

\begin{verbatim}
class
    HOLA_MUNDO
create
    creacion_por_defecto
feature {NONE} -- Inicializacion
    creacion_por_defecto
        -- Se define la creacion de la clase.
        do
            print ("Hola, mundo!%N")
        end
\end{verbatim}

\section{Clases}
Existen dos relaciones entre clases:
\begin{itemize}
\item Una clase clase A puede hacer uso de otra B. En este caso A se llama la clase cliente y C la clase proovedora.
Se permite una relacion cliente-prooveder ciclico.
\item Una clase A puede ser heredera de otra C, que proporciona a A todos las funciones y propiedades (features) de C.
No se permite una relacion ciclica.
\end{itemize}

\begin{verbatim}
class
    CAJA_AHORRO
 
inherit
    CUENTA
        redefine 
            -- Se marca el metodo que se va a redefinir.
            deposito
    end
 
feature -- Cambio de estado
 
    deposito (suma: INTEGER)
            -- Le suma una cantidad a la cuenta.
        do
            ... Nueva implementacion
        end
 
    ... Mas metodos
 
end -- clase CAJA_AHORRO
\end{verbatim}

\subsection{Estructura general}
En Eiffel tenemos una clase de la cual heredan todas, llamada ANY y otra clase que es hija de todas las 
que no tienen hijos, llamada NONE.
El sentido de estas clases parte de la visibilidad que tienen las features. A feature se puede dar visibilidad a NONE,
lo cual hace que solo pueda ser llamada internamente, o no asignarle ninguna visibilidad, lo que toma como defecto ANY,
que hace que ese feature sea visible por todas las clases.

\section{Manejo de memoria}

La filosofía de Eiffel apunta al desarrollo de código simple y reutilizable por parte del programador. Como se sabe
que cumplir este objetivo no es sencillo, se trata de facilitarle la tarea al programador. El manejo de memoria
en Eiffel se adecúa a este pensamiento, tratando de que el desarrollador no tenga que preocuparse por la misma.

El manejo de memoria manual agregaría demasiada complejidad al sistema que, probablemente, no haga la diferencia
en cuanto a la usabilidad y funcionalidad del producto final. Por otro lado, los errores que surgen debido a un
incorrecto manejo de memoria son comunes y, usualmente, fuente de bugs dificiles de corregir. Esto le brinda un
respaldo al programador, que puede confiar en Eiffel completamente en cuanto a la memoria, teniendo garantía
que ese tema no será fuente de problemas.

\subsection{Eiffel Garbage Collector (GC)}

El recolector de basura de Eiffel no solo libera la memoria para que pueda ser utilizada por otros objetos del programa,
sino que le devuelve la memoria al sistema operativo, dejando que la misma pueda ser utilizada por otra parte de la
aplicación (indepenendiente del módulo que este programado en Eiffel) u otro programa. Esta característica es muy importante,
ya que se podría dar el caso en el que nuestro sistema Eiffel requiere mucha memoria, por ende se la pide al sistema operativo,
pero más adelante esta memoria es liberada, pero seguiría estando alocada por nuestro sistema, perjudicando el desempeño
del sistema operativo.

Como se debe devolver memoria al sistema operativo, el lenguaje no puede recurrir a un simple ``malloc()'', ya que dicha instrucción
no tiene manera de devolver la memoria al sistema operativo. Para poder lograr esto, Eiffel tiene su propio manejo de memoria,
en el que le pide pedazos (chunks) de memoria directamente al kernel.

\subsection{Algoritmos del GC}

El recolector de basura de Eiffel usa varios algoritmos que pueden ser usados en conjunto o independientemente uno de otro,
dependiendo de la necesidad de memoria que se requiera liberar. Esto significa que el algoritmo a utilizar (o el conjunto)
se decide en base a la urgencia que se tenga de liberar memoria.

Los utilizados son:

\begin{itemize}
\item Generation Scavenging
\item Mark and Sweep
\item Memory Compaction
\end{itemize}

\subsubsection{Generation Scavenging}

Este método se basa en la idea de que los objetos recién creados tienen menos probabilidad de sobrevivir que aquellos que están en el
programa hace más tiempo. Se divide a los objetos en distintas generaciones.

Una generación es recolectada cuando alcanza una cierta cantidad de elementos. Cuando esta es recolectada, los sobrevivientes envejecen y,
llegados a una cierta edad, se los pasa a la siguiente generación. Se puede ver la diferenciación entre objetos en distintas generaciones
mediante la siguiente ilustración.

Los objetos que son promovidos de una generación a otra son los que sobrevivieron varias etapas de recolección. Al haber sobrevivido
la recolección en reiteradas ocasiones, se considera que estos son menos propensos a quedar dereferenciados, razón por la cual se
los promueve a la generación más vieja, con menos probabilidad de ser recolectada.

\subsubsection{Mark and Sweep}

El algoritmo de recolección de marcado y barrido (o mark and sweep) cuenta, como su nombre bien lo indica, de dos etapas marcadas.
La primera, de marcado, se encarga de recorrer todo el arbol de objetos que se encuentren en memoria y marca aquellos que cuenten
con una referencia desde otro objeto. De esta manera, al finalizar la etapa de marcado, tendremos una cierta cantidad de objetos
alcanzables y otros que, al no ser referenciados por ningún otro objeto, no se puede alcanzar.

La etapa de barrido se encarga de eliminar de la memoria aquellos objetos que no cuenten con referencias. De esta manera estamos
liberando la memoria de aquellos objetos que ya no pueden ser usados porque no pueden ser referenciados.

Las raices desde donde se empieza a recorrer son los objetos raiz del sistema y entidades locales. Por este motivo, el algoritmo
es capaz de identificar y barrer correctamente cuando hay referencias circulares.

A continuación una ilustración para distintas etapas del algoritmo:


\subsubsection{Memory Compaction}

El objetivo de este algoritmo es el de compactar la memoria que esta siendo utilizada y, de esta manera, recuperar porciones de
memoria que antes no eran utilizables debido a su espacio reducido. Al compactar la memoria, la cantidad recuperada puede llegar
a ser tan grande se puede dar el caso en el que se devuelva parte de esta memoria al sistema operativo.

El algoritmo divide la memoria en n bloques y por medio de n-1 ciclos la compacta, realizando el cambio en distribución que se
aprecia con la siguiente ilustración:

La ganancia que se obtiene mediante este algoritmo puede no ser apreciable a simple vista, pero sus beneficios son bastante
importantes, ya que la suma de porciones pequeñas de memoria puede ser muy grande en su totalidad. El problema de la fragmentación
es un problema muy interesante con muchas maneras distintas de solucionar.

\begin{figure}[h!]
  \caption{Generation Scavenging}
  \centering
    \includegraphics[width=0.4\textwidth]{pics/GenerationScavenging.png}
\end{figure}

\begin{figure}[h!]
  \caption{Mark And Sweep}
  \centering
    \includegraphics[width=0.6\textwidth]{pics/MarkAndSweep.png}
\end{figure}

\begin{figure}[h!]
  \caption{Memory Compaction}
  \centering
    \includegraphics[width=0.4\textwidth]{pics/MemoryCompaction.png}
\end{figure}

\newpage

\section{Diseño por Contratos}

Un contrato en Eiffel es muy similar a un contrato en la vida real entre dos personas o dos compañias. Puede ser fácilmente expresable en forma de cuadro.
Esta característica del lenguaje lo hace muy interesante, ya que es uno de los primeros lenguajes que soporta diseño por contratos de manera directa.
Los contratos en Eiffel no son emulados, sino que son una parte central y característica del lenguaje. Esta herramienta permite un control de flujo
del programa muy beneficiosa e innovadora.

Un ejemplo, muy básico por cierto, acerca de lo que entendemos como un contrato entre dos partes:

\begin{figure}[h!]
  \centering
    \includegraphics[width=0.6\textwidth]{pics/DesignByContract.png}
\end{figure}

Aunque muy basico, este ejemplo nos muestra que, en presencia de un contrato, hay represalias si alguno de los firmantes no cumple con su parte
del contrato. Esta analogía puede ser llevada directamente a un lenguaje de programación en el que, mientras el contrato sea cumplido la ejecución
continúa sin problemas y, si el contrato no es cumplido, se debe realizar alguna acción.

\subsection{Idea central del diseño por contratos}

La idea central del diseño por contratos es una metáfora acerca de como los elementos del sistema colaboran entre si sobre una base de obligación y
beneficios mutuos. La metáfora, como se dijo anteriormente, tiene origen en la vida de negocios, en donde un cliente y un proveedor se ponen de acuerdo
en un contrato que define que:

\begin{itemize}
\item El proveedor debe proveer cierto producto (obligación) y el cliente tiene que pagar por este producto (beneficio)
\item El cliente debe pagar (obligación) y recibe, a cambio, el producto (beneficio)
\end{itemize}

Ambos lados deben satisfacer ciertas obligaciones, ya sean leyes o regulaciones, que aplican a todos los contratos. De manera similar, si
una rutina de una clase provee cierta funcionalidad, puede esperar que cierta condición sea garantizada por el módulo cliente que la
invoca. La precondición de la rutina es una obligación para el cliente y un beneficio para el proveedor, ya que lo libera de tener que
manejar los casos fuera de la precondición. El proveedor debe garantizar que cierta propiedad, a su vez, se cumpla al terminar la
ejecución del método. La postcondición de la rutina es una obligación para el proveedor y, obviamente, un beneficio para el cliente. A su vez
una parte del contrato pide que cierta propiedad se mantenga a lo largo de la ejecución del programa, la invariante.

\subsection{Elementos en el diseño por contratos}

Los elementos que Eiffel maneja para poder facilitar el diseño por contratos son tres:

\begin{itemize}
\item Precondiciones (\textbf{require})
\item Postcondiciones (\textbf{ensure})
\item Invariantes de clase (\textbf{invariant})
\end{itemize}

Las precondiciones son aquellas condiciones que se tienen que cumplir antes de entrar al método invocado. Las postcondiciones son las condiciones
que tiene que cumplir el método una vez finalizado, es decir, en que estado puede quedar el sistema o la clase luego de que se llamo a ese método.
Las invariantes de clase son condiciones que deben ser cumplidas en tiempo de ejecución. No se puede romper con la condición de una invariante
de clase en ningún lugar del método.

Como ejemplo, demostramos como se modelaría una cuenta bancaria utilizando diseño por contratos:

\begin{verbatim}
Class
    CUENTA
features -- Accesso
    balance: INTEGER
    -- Balance actual
    contador_depositos: INTEGER is
    -- cantidad de depositos hechos
        do ... end

feature -- Cambia un elemento
    Depositar (suma: INTEGER) is
    -- Le agrega la cantidad suma a la cuenta
    require
        no_negativo: suma >= 0
    do ...
    ensure
        deposito_sumado: contador_depositos = old contador_depositos + 1
        actualizado: balance = old balance + suma
    end
feature {NONE} -- Implemenentacion
    depositos: DEPOSIT_LIST
    -- Lista de depositos
    invariant
        balance_consistente: (depositos /= Void) implies (balance = depositos.total)
        zero_si_no_hay_depositos: (depositos = Void) implies (balance = 0)
end
\end{verbatim}

\section{Manejo de excepciones}

Toda rutina tiene un contrato que debe cumplir, lo hace a través del uso de otras rutinas que a su vez también deben cumplir un contrato.
Cualquiera de estas operaciones puede fallar y ocasiona una excepción en la rutina desde la que se llamo. Como se dijo antes, cuando
no se cumple un contrato, se debe tomar una represalia. En este caso, lo que se hace cuando no se cumple alguna parte del contrato es
lanzar una excepción y propagarla hasta que alguien se haga cargo de la misma.

Para manejar las excepciones se usa la clausula \textbf{rescue} y, dentro de esta se puede utilizar \textbf{retry}. Se entra al bloque
definido por el rescue cuando ocurra una excepción en tiempo de ejecución. Este bloque sirve para intentar resolver el problema que
origino la excepción. El programador tiene la posibilidad de resolver los problemas y volver a intentar ejecutar el método mediante
el uso de retry.

Un ejemplo para que quede un poco más claro, referenciando a la lectura de un caracter desde un archivo:

\begin{verbatim}
read_proximo_char(f: FILE) is
    -- Deja el siguiente carácter en ultimo_char
    -- Si no se puede leer, se deja fallo en True
    require
        readable: file.readable
    local
    imposible: BOOLEAN
    do
        if imposible then
            fallo := True
        else
            ultimo_char := read_bajo_nivel(f)
    end
    rescue
        imposible := True
        retry
end
\end{verbatim}

Otro ejemplo que pone en práctica la clausula retry es el de la transmición de un paquete a través de un canal. El
paquete se intenta mandar un numero finito de veces hasta que se considera que no se debe intentar nuevamente.

\begin{verbatim}
transmitir: (p: PAQUETE)
            -- Transmitir paquete p
        require
            paquete_no_void: p /= Void
        local
            cantidad_intentos: INTEGER
            r: RANDOM_NUMBER_GENERATOR
        do
            -- Se intenta mandar el paquete
            canal.enviar (p)
        rescue
            if cantidad_intentos < maximo_intentos then
                r.next
                -- Se espera entre los intentos de envio.
                wait_millisecs (r.value_between (20, 500))
                cantidad_intentos := cantidad_intentos + 1
                -- Se vuelve a intentar
                retry
            end
        end
\end{verbatim}

\section{Herencia}

Al ser Eiffel un lenguaje orientado a objetos, provee de ciertas herramientas para facilitar la herencia
entre clases. Las clausulas que Eiffel define tienen como único objetivo el de adecuar la herencia a las
necesidades que el programador tenga. Las clausulas que se definen son las siguientes:

\begin{itemize}
\item rename
\item export
\item undefine
\item redefine
\item select
\end{itemize}

\subsection{redefine}

Esta clausula permite redefinir un feature de la clase padre, dejando el resto de las implementaciones
a cuenta de la clase padre.

\begin{verbatim}
class
	CUENTA_AHORRO
inherit
    CUENTA
    redefine deposito end
    feature – Cambio de elemento
        deposito(suma: Integer) is
            – Otra logica para el deposito.
            do ... end
        end
\end{verbatim}

Aquí estamos redefiniendo el comportamiento del método deposito para la clase cuenta ahorro.

\subsection{rename}

Como Eiffel soporta herencia múltiple, se puede dar el caso en el que estemos heredando de
dos clases que compartan nombre entre métodos o atributos. Eiffel facilita la resolución
de colisiones mediante la clausula rename, que permite cambiarle el nombre tanto a métodos
como a atributos heredados.

\begin{verbatim}
class
    ARRAYED_LIST [ G ]
inherit
    LIST [ G ]
    ARRAY [ G ]
    rename
        cuenta as capacidad, item as array_item
    end
    feature
    ...
end -- clase ARRAYED_LIST
\end{verbatim}

\subsection{undefine}

Nuevamente, debido al soporte de herencia múltiple por parte de Eiffel, se puede querer
deshabilitar la implementación de cierto feature de alguna de las clases padres. Esto
puede deberse a que se quiere utilizar únicamente alguna de las implementaciones de
cierto método que esta definido más de una clase padre.

\begin{verbatim}
class D inherit
    A
        rename
            g as f
            -- g es un feature implementado por A
        undefine
            f
            -- se deshabilita f
        end
    B
        undefine f end
        -- f estaba efectivo en B
    C
        -- se utilizara la implementacion de f de C
    feature
    ...
\end{verbatim}

\subsection{select}

Similar al caso anterior, se heredan mismos features y se quiere elegir cual será el utilizado por la clase
que hereda.

\begin{verbatim}
class AYUDANTE inherit
    PROFESOR
        rename
            corregir as corregir_estricto
        select
            corregir_estricto
    end
    ESTUDIANTE
        rename
            corregir as corregir_bondadoso
    end
...
\end{verbatim}

Aquí, cuando un ayudante intente corregir, se seleccionará al método que ahora se llama corregir estricto, que
fue seleccionado de la clase padre profesor.

\subsection{export}

Mediante esta clausula se puede cambiar el estado de visibilidad de un feature que es heredado. Debemos ser cuidadosos
y pensar detenidamente cuando este mecanismo debe ser utilizado, ya que un mal uso de esta clausula podría desembocar
en problemas de visibilidad y de seguridad al exponer demasiado acerca de una clase.

\begin{itemize}
\item NONE: cambia el feature a secreto
\item ANY:  cambia el feature a exportado
\end{itemize}

\begin{verbatim}
class MUJER [ G ] inherit
    PERSONA [ G ]
        rename
            años as edad
        export
            {NONE} edad
            --{ANY} algun atributo exportado
    end
\end{verbatim}

\section{Polimorfismo}

En Eiffel se permite la redefinicion de features. Una clase puede redefinir una o todos los features que esta heredando. 
Para un atributo o funcion, la redefinición puede afectar al tipo, remplazando al original por su descendiente, para una 
rutina puede tambien afectar su implementacion, reemplazando el cuerpo original por uno nuevo.

Supongamos la clase Poligono, donde sus features incluyen un array de puntos representando los vertices y una funcion 
perimetro que computa el perimetro del poligono, una clase que hereda de poligono podria ser:

\begin{verbatim}
class RECTANGULO
    inherit
        POLIGONO
            redefine
                perimetro
            end
 
feature -- Las features de rectangulo, como puede ser:
 
    lado1: REAL
    lado2: REAL
 
    perimetro: REAL
            -- Rectangulo-version especifica
        do
            Resultado := 2 * (lado1 + lado2)
        end
 
... Otros features de Rectangulo ...
\end{verbatim}

En este caso es recomendable redefinir el feature del perimetro del rectangulo por uno con un algoritmo mas simple y eficiente.
Otros descendientes de Poligono pueden tener su propia redefinicion de perimetro, la version a usar en cada llamado depende 
del objeto al que se le esta llamando. Consideremos el siguiente ejemplo:

\begin{verbatim}
p: POLIGONO
    r: RECTANGULO
            ... 
 
            create p
            create r 
            ...
            if c then
                p := r
            end
            print (p.perimetro)
\end{verbatim}

Si la condicion c es falsa, a p se le va a asignar un objeto del tipo Poligono para el calculo del perimetro, que usara el definido 
en la clase Poligono. En caso contrario, a p se le va a asignar un objeto del tipo Rectangulo, y el llamado a perimetro se realizara
con la definición de la clase Rectangulo. Esto se llama dynamic binding o asignacion dinamica.

\section{Concurrencia}

\subsection{El modelo SCOOP}

El modelo SCOOP define una manera en la que un programa orientado a objetos es escrito sin el uso de threads, locks u otra implementación
típica de programación concurrente. Esto permite que el compilador o entorno optimice la cantidad de concurrencia, así como también
elimina las típicas fallas de diseño, como puede ser la conocida como ``deadlock''. Se llama ``deadlock'' a lo que ocurre cuando dos
hilos de ejecución quedan bloqueados para siempre, esperandose uno al otro.

\subsection{Ejemplo ``deadlock'' en Java}

Aquí dejamos un ejemplo en Java que ocasiona un deadlock:

\begin{verbatim}
public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}
\end{verbatim}

Cuando se ejecute Deadlock, es extremadamente probable que ambos hilos se bloqueen cuando intenten invocar bowBack. Ningun bloqueo va a finalizar
debido a que cada hilo está esperando que el otro termina de ejecutar bow.

El objetivo de SCOOP es abstraer la concurrencia a un nivel superior a las técnicas de disponibles comúnmente. Es una extensión del lenguaje Eiffel que facilita la
concurrencia. La unica keyword que agrega esta extensión es separate. Sin embargo, es capaz de proveer todo el poder de la concurrencia.

Un objeto definido como ``separate'' es manejado por el procesador SCOOP, que es diferente del procesador que maneja al objeto que lo referencia. El procesador
SCOOP es la noción abstracta de el hilo autónomo de control, que maneja la ejecución de operaciones sobre uno o más objetos. Los procesadores SCOOP son independientes
de los mecanismos subyacentes como hilos, núcleos de procesamiento múltiples y sistemas de computación distribuidos.

\subsection{Implementación}

El secreto de la programación concurrente en Eiffel es que el lenguaje se encarga de las partes complejas, como puede ser la sincronización, para concentrarse
plenamente en lo que se esta programando y no de que manera.

Ejemplo acerca de la sintaxis de las llamadas concurrentes:

\begin{verbatim}
...
atributo_concurrente: separate ALGUN_TIPO
    ...
    rutina_invocada
        -- Una rutina
        do
            atributo_concurrente.algun_feature   -- Invalido, no se puede llamar a un feature de un atributo de clase separate
            rutina_encapsulada (atributo_concurrente) -- Atributo separate pasado por parametro
        end
 
    rutina_encapsulada (parametro: separate SOME_TYPE)
        -- Otra rutina
        do
            parametro.algun_feature    -- Valido, parametro no es de clase
        end

\end{verbatim}

\subsection{Ejemplos concurrentes}

A continuación presentamos un ejemplo de SCOOP, en el que tenemos un micro con pasajeros que implementan
la interfaz (que es una clase con clausulas ``deferred'') actor.

\begin{verbatim}
class
    MICRO_POBLADO

create
    make

feature -- Inicializacion

    make
        -- Creacion.
        local
            i: INTEGER
            t_pasajero: separate PASAJERO
        do
            create estacion.make
            create micro.make_con_estacion(0, estacion)
            lanzar_actor (micro)

            from
                i := 1
            until
                i > passengers
            loop
                create t_pasajero.make_con_estacion(i, estacion)
                lanzar_actor (t_pasajero)
                i := i + 1
                (create {EXECUTION_ENVIRONMENT}).sleep (500 * 1000000)
            end
        end

feature {NONE} -- Implementacion

    lanzar_actor(un_actor: separate ACTOR)
            -- Launch an actor.
        do
            un_actor.live
        end

    pasajeros: INTEGER = 30

    micro: separate MICRO

    estacion: separate ESTACION

end -- class MICRO_POBLADO

\end{verbatim}

Aquí se crea el micro con pasajeros y, hasta que la cantidad de pasajeros llegue al máximo,
se llama al método ``live'' de los actores que se suben al micro. A continuación vemos la
clase Actor que hace las veces de interfaz que luego implementaran otras clases:

\begin{verbatim}
deferred class
    ACTOR

inherit
    SHARED_RANDOM
        redefine
            out
        end

feature {NONE} -- Creacion

    make_con_estacion(a_id: INTEGER; una_estacion: separate estacion)
            -- Creacion.
        do
            id := a_id
            estacion := una_estacion
            create random.set_seed (id)
        end

feature -- Accesso

    id: INTEGER
            -- Id del actor

    out: STRING
            -- Como representamos al actor con un string.
        once
            Result := type + "-" + id.out
        end

    type: STRING
        -- Tipo de actor. Se definirá en la clase que hereda.
        deferred
        end

feature {MICRO_POBLADO} -- Outline de operaciones basicas

    live
        -- Este es el ciclo de vida del actor, llamado desde MICRO_POBLADO.
        do
            from

            until
                over
            loop
                step
            end
        end

feature {NONE} -- Implementacion

    over: BOOLEAN
        -- Termino el tiempo de vida?

	step
        -- Realizar un paso.
        deferred
        end

    estacion: separate ESTACION
			-- Referencia a la separate estacion.

invariant

    estacion_not_void: estacion /= Void

end
\end{verbatim}

En esta clase se define un esquema de lo que hará cada actor que se sube al micro. Vemos que ejecuta
acciones hasta que su tiempo de vida ha finalizado. Vemos que se hace uso de la clausula ``deferred''
para referirse a métodos cuya implementación estará ligada a las clases que hereden de esta.

Un ejemplo de uno de los actores que podría formar parte de este esquema es el micro en sí, cuya
implementación podría ser algo de la siguiente forma:

\begin{verbatim}
class
    MICRO
inherit
    ACTOR

create {MICRO_POBLADO}

    make_con_estacion

feature {NONE} -- Implementacion

    step
            -- Un paso. Redefinicion.
        do
            io.put_string (out + " esta llegando a la estacion%N")
            entrar (estacion)
            io.put_string (out + " entro a la estacion%N")
            levantar_pasajeros (estacion)
            salir (estacion)
            io.put_string (out + " se fue de la estacion%N")
            (create {EXECUTION_ENVIRONMENT}).sleep (2000 * 1000000)
        end

    entrar (una_estacion: separate estacion)
        require
            una_estacion /= void
            not una_estacion.bus_is_waiting
        do
            una_estacion.bus_enter
        end

    levantar_pasajeros (una_estacion: separate estacion)
        require
            una_estacion /= void
        do
            una_estacion.levantar_pasajeros
        end

    salir (una_estacion: separate estacion)
        require
            una_estacion /= void
        do
            una_estacion.leave
        end

    type: STRING = "Micro"
            -- El tipo de la clase es Micro

end
\end{verbatim}

Este ejemplo sirve para demostrar como cada actor, sea cual fuere su clase final correría utilizando
SCOOP, y los actores que viven dentro del micro tendrían que comunicarse entre si concurrentemente.
Obviamente, como ya dijimos, nosotros no nos tenemos que preocupar por la concurrencia, ya que es
SCOOP el que se encarga de eso.

\section{Conclusiones}

Uno de los grandes beneficios de utilizar Eiffel es que, al estar el lenguaje totalmente pensado para
realizar programación orientado a objetos, esta tarea se ve simplificada. Se podría decir que casi todas
las cláusulas que Eiffel introduce están pensadas para minimizar las dificultades que puede tener un programador
al codificar una aplicación con un modelo de objetos.

Debido a su gran versatilidad, Eiffel no tiene un área de aplicación particular, sino que la filosofía
que caracteriza al lenguaje permite que el mismo se adapte a cualquier modelo de la vida real. Otro punto
fuerte que tiene Eiffel a la hora de diseñar un sistema es que nos brinda una solución integral, que es
EiffelStudio. En este framework podemos pasar por todas las etapas de una aplicación o sistema.

El diseño por contrato es algo que se embebe en los sistemas actuales en los que se quiere mantener un
gran nivel de control sobre los métodos. El uso de precondiciones facilita mucho la programación defensiva,
en la que nos hacemos cargo de todo lo que pueda salir mal en nuestro método o clase. El utilizar las
precondiciones, estamos limitando el número de situaciones que vamos a manejar y delegamos algunas otras
a la clase o método que nos invoca. Este mecanismo es muy cómodo y útil, y el hecho de que este integrado
en el modelo Eiffel lo hace muy robusto.

Con respecto a la programación concurrente, mi opinion es que el modelo que plantea Eiffel, aunque muy
cómodo, puede no gustarle a muchos, puesto que el control no lo tiene uno, sino que se lo delega
al lenguaje.

\section{Bibliografía}

\begin{itemize}
\item \href{http://docs.eiffel.com/}{Documentación Eiffel}
\item \href{http://www.eiffel.com/developers/faqs/eiffel-language.html}{Eiffel FAQ}
\item \href{http://archive.eiffel.com/doc/online/eiffel50/intro/language/tutorial.pdf}{Eiffel Tutorial}
\item \href{http://goo.gl/GV1Uf}{The Road To Eiffel}
\item \href{http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-367.pdf}{Eiffel ECMA Standard}
\end{itemize}

\end {document}
